#include "stdafx.h"
#include "Cast.h"
#include <math.h>

std::wstring wstring_cast(const float& arg)
{
	std::wstring result;
	int intValue = (int)floorf(arg);
	int decimalValue = (int)((arg - floor(arg)) * 100.0f + 0.5f);
	result = wstring_cast(intValue);
	result += L'.';
	result += (L'0' + (decimalValue / 10));
	result += (L'0' + (decimalValue % 10));
	return result;
}

std::string string_cast(const int& num) {
	return basic_string_cast<char>(num);
}
std::wstring wstring_cast(const int& num) {
	return basic_string_cast<wchar_t>(num);
}

inline wchar_t C2W(char ch)
{
	return (wchar_t)ch;
}

wchar_t* cstr2wstr(const char *pcstr, wchar_t *pwstr)
{
	wchar_t* result = pwstr;
	if(pwstr != NULL && pcstr != NULL) {
		while(*pcstr != 0) {
			*pwstr = C2W(*pcstr);
			pwstr++;
			pcstr++;
		}
		*pwstr = L'\0';
		return result;
	}
	return 0;
}

std::wstring cstr2wstr(const char *pcstr)
{
	int length = strlen(pcstr);
	wchar_t* wstr = new wchar_t[length + 1];
	cstr2wstr(pcstr, wstr);
	std::wstring result = wstr;
	delete [] wstr;
	return result;
}

bool utf82unicode(const char* inStr, wchar_t* outStr)
{
	int inLen = strlen(inStr);
	int outLen = 0;
	return utf82unicode(inStr, inLen, outStr, outLen);
}

/*inline*/ bool utf82unicode(const char* inStr, const int inLen, wchar_t* outStr, int& outLen)
{
	if(!inStr || !outStr) {
		return false;
	}
	
	int charIndex = 0;
	int unicodeIndex = 0;
	while(charIndex < inLen) {
		//read one char.
		int charBytes = 0;
		const char* utf8 = &inStr[charIndex];
		wchar_t* unicodeChar = &outStr[unicodeIndex];
		memset((char*)unicodeChar, 0x0, sizeof(wchar_t));

		if( (utf8[0] & 0x80) == 0x0) {
			charBytes = 1;
			*unicodeChar = utf8[0];
		} else if( (utf8[0] & 0xE0) == 0xC0 ) {
			charBytes = 2;
			*unicodeChar = (utf8[0] & 0x1F) << (6);
		} else if( (utf8[0] & 0xF0) == 0xE0 ) {
			charBytes = 3;
			*unicodeChar = (utf8[0] & 0x0F) << (12);
		} 
#if 0
		else if( (utf8[0] & 0xF8) == 0xF0 ) {
			charBytes = 4;
			*unicodeChar = (utf8[0] & 0x07) << (18);
		} else if( (utf8[0] & 0xFC) == 0xF8 ) {
			charBytes = 5;
			*unicodeChar = (utf8[0] & 0x03) << (24);
		} else if( (utf8[0] & 0xFE) == 0xFC ) {
			charBytes = 6;
			*unicodeChar = (utf8[0] & 0x01) << (30);
		}
#endif	
		for(int c = 1; c < charBytes; c++) {
			*unicodeChar |= (utf8[c] & 0x3F) << (charBytes - c - 1) * 6;
		}

		if(charBytes == 0) {
			charIndex ++;
		} else {
			charIndex += charBytes;
			unicodeIndex ++;
		}
		
	}
	//
	outLen = unicodeIndex;
	outStr[outLen] = 0;

	return true;
}

bool unicode2utf8(const wchar_t* inStr, char* outStr)
{
	int inLen = wcslen(inStr);
	int outLen = 0;
	return unicode2utf8(inStr, inLen, outStr, outLen);
}

bool unicode2utf8(const wchar_t* inStr, const int inLen, char* outStr, int& outLen)
{
	if(!inStr || !outStr) {
		return false;
	}
	
	int unicodeIndex = 0;
	char * outChar = outStr;
	while(unicodeIndex < inLen) {
		wchar_t curUnicodeChar = *(inStr + unicodeIndex);

		int charBytes = 0;
		if(curUnicodeChar < 0x7F)
		{
			charBytes = 1;
			*outChar++= curUnicodeChar & 0x7F;
		}
		else if(curUnicodeChar < 0x7FF)
		{
			charBytes = 2;
			*outChar++=0xC0 | (curUnicodeChar >> 6);
		}
		else if(curUnicodeChar < 0xFFFF)
		{
			charBytes = 3;
			*outChar++=0xE0 | (curUnicodeChar >> 12);
		}
#if 0
		else if(curUnicodeChar < 0x1FFFFF)
		{
			charBytes = 4;
			*outChar++=0xF0 | (curUnicodeChar >> 18);
		}
		else if(curUnicodeChar < 0x3FFFFFF)
		{
			charBytes = 5;
			*outChar++=0xF8 | (curUnicodeChar >> 24);
		}
		else if(curUnicodeChar < 0x7FFFFFFF)
		{
			charBytes = 6;
			*outChar++= 0xFC | (curUnicodeChar >> 30);
		}
#endif
	
		for(int c = 1; c < charBytes; c++) {
			*outChar++ = 0x80 | ((curUnicodeChar >> (charBytes - c - 1) * 6) & 0x3F);
		}

		unicodeIndex ++;
		
	}
	*outChar = 0;
	outLen = outChar - outStr;


	return true;
}